// Package ioc
// Created by GoLand
// @User: lenora
// @Date: 2023/12/17
// @Time: 15:41

package ioc

import (
	"camp/microbook/constant"
	dao2 "camp/microbook/interactive/repository/dao"
	"camp/microbook/internal/repository/dao"
	"camp/microbook/pkg/gormx"
	"camp/microbook/pkg/logger"
	"context"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/spf13/viper"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	glogger "gorm.io/gorm/logger"
	"gorm.io/plugin/opentelemetry/tracing"
	gormprometheus "gorm.io/plugin/prometheus"
	"time"
)

func InitDb(log logger.Logger) *gorm.DB {
	type config struct {
		DSN string `yaml:"dsn"`
	}
	var cfg = config{
		DSN: "默认值",
	}
	err := viper.UnmarshalKey("db", &cfg)
	if err != nil {
		panic(err)
	}

	db, err := gorm.Open(mysql.Open(cfg.DSN), &gorm.Config{
		Logger: glogger.New(gormLoggerFn(log.Debug), glogger.Config{
			//慢查询日志
			//0-所有都打印
			SlowThreshold: 0,
			Colorful:      true,
			LogLevel:      glogger.Error, //打印所有级别的日志
		}),
	})
	if err != nil {
		panic(err)
	}

	err = db.Use(gormprometheus.New(gormprometheus.Config{
		DBName:          "microbook",
		RefreshInterval: 15,
		MetricsCollector: []gormprometheus.MetricsCollector{
			&gormprometheus.MySQL{
				VariableNames: []string{"thread_running"},
			},
		},
	}))
	if err != nil {
		panic(err)
	}

	callback := gormx.NewCallbacks(prometheus.SummaryOpts{
		Namespace:  constant.NAMESPACE,
		Subsystem:  constant.SUBSYSTEM,
		Name:       "gorm_db",
		Objectives: constant.Objectives,
	})

	if err := db.Use(callback); err != nil {
		panic(err)
	}

	err = db.Use(tracing.NewPlugin(tracing.WithoutMetrics(),
		tracing.WithDBName("microbook")))
	if err != nil {
		panic(err)
	}

	if err := dao.InitTables(db); err != nil {
		panic(err)
	}

	if err := dao2.InitTables(db); err != nil {
		panic(err)
	}

	return db
}

type gormLoggerFn func(msg string, fields ...logger.Field)

func (g gormLoggerFn) Printf(s string, i ...interface{}) {
	g(s, logger.Field{Key: "arg", Value: i})
}

func InitCollection(mdb *mongo.Database) error {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	col := mdb.Collection("articles")
	_, err := col.Indexes().CreateMany(ctx, []mongo.IndexModel{
		{Keys: bson.D{bson.E{"id", 1}}, Options: options.Index().SetUnique(true)},
		{Keys: bson.D{bson.E{"author_id", 1}}},
	})
	if err != nil {
		return err
	}

	proCol := mdb.Collection("published_articles")
	_, err = proCol.Indexes().CreateMany(ctx, []mongo.IndexModel{
		{Keys: bson.D{bson.E{"id", 1}}, Options: options.Index().SetUnique(true)},
		{Keys: bson.D{bson.E{"author_id", 1}}},
	})
	return err
}
